//////////////////////////////////////
// Fast Container Library           //
// MIT License - Copyright (c) 2012 //
//////////////////////////////////////

#pragma once

#include "vector.h"
#include "vector_set.h"


FC_NAMESPACE_BEGIN


template <class T, class ParallelContainer, class Allocator>
class parallel : public vector<T, Allocator>
{
public:
	typedef parallel<T, ParallelContainer, Allocator>	this_type;
	typedef vector<T, Allocator>						base_type;
	typedef ParallelContainer							cell_type;
	typedef typename base_type::size_type				size_type;
	typedef typename base_type::value_type				value_type;
	typedef typename base_type::pointer					pointer;
	typedef typename base_type::const_pointer			const_pointer;
	typedef typename base_type::iterator				iterator;
	typedef typename base_type::const_iterator			const_iterator;
	typedef typename base_type::allocator_type			allocator_type;

	using base_type::size;
	using base_type::begin;
	using base_type::end;

	parallel()
		: base_type(), m_cells()
		{
		}

	explicit parallel( allocator* alloc )
		: base_type(alloc), m_cells()
		{
		}

	explicit parallel( size_t n, const T& value = T(), const allocator_type& alloc = allocator_type() )
		: base_type(n, value, alloc), m_cells()
		{
		}

	template<class Iter>
		parallel( Iter first, Iter last )
		: base_type(first, last), m_cells()
		{
		}

	parallel( const this_type& x )
		: base_type(x), m_cells(x.m_cells)
		{
		}

	~parallel()
		{
		}

	this_type& operator =( const this_type& x )
	{
		if( this != &x )
		{
			base_type::operator =(x);
			m_cells = x.m_cells;
		}
		return *this;
	}

	this_type& operator =( const base_type& x )
	{
		base_type::operator =(x);
		return *this;
	}

	void clear()
	{
		base_type::clear();
		m_cells.clear();
	}

	void bind( typename cell_type::value_type pos )
	{
		m_cells.push_back(pos);
	}

	void bind( const_iterator it )
	{
		m_cells.push_back( typename cell_type::value_type(it - begin()) );
	}

	void vacate()
	{
		m_cells.clear();
	}

	void execute()
	{
		if( m_cells.empty() )
			;
		else if( m_cells.size() == 1 )
		{
			base_type::erase( base_type::begin() + *m_cells.begin() );
		}
		else
		{
			typename cell_type::const_iterator last = m_cells.begin();
			typename cell_type::const_iterator c = last + 1;
			iterator base = begin();
			iterator it = base + *last;

			for( ; c != m_cells.end(); ++c )
			{
				it = _Destination_Copy( base + *last + 1, base + *c, it );
				last = c;
			}

			it = _Destination_Copy( base + *last + 1, end(), it );
			base_type::erase( it, end() );
		}
		vacate();
	}

	cell_type& get_cells()				{ return m_cells; }
	const cell_type& get_cells() const	{ return m_cells; }

	void swap( this_type& x )
	{
		base_type::swap( x );
		m_cells.swap( x.m_cells );
	}


protected:
	FC_FORCE_INLINE iterator _Destination_Copy( iterator first, iterator last, iterator dest )
	{
		while( first != last )
			*dest++ = *first++;

		return dest;
	}

	cell_type m_cells;

};




FC_NAMESPACE_END
